#include "Mutex_Wrapper.h"

Mutex_Wrapper::Mutex_Wrapper(bool _throwexception) throw(runtime_error) {
   throw_exception = _throwexception;
   int result = 0;
   tid = -1;

   pthread_mutexattr_t mutex_attr;
   memset(&mutex_attr,0,sizeof(mutex_attr));

   if ((result = pthread_mutexattr_init(&mutex_attr)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::POSIXMutex() - Could not init mutex attribute.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
      return;
   }

   if ((result = pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_RECURSIVE)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::POSIXMutex() - Could not set mutext attribute.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
      return;
   }

   //pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_ERRORCHECK);
   //pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_NORMAL);

   if ((result = pthread_mutex_init(&mutex, &mutex_attr)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::POSIXMutex() - Could not initialise mutex variable.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
   }
};


Mutex_Wrapper::~Mutex_Wrapper() {
   int result = 0;
   if ((result = pthread_mutex_destroy(&mutex)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::~POSIXMutex() - Failure during destruction of mutex.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
   }
};


void Mutex_Wrapper::lock() throw(runtime_error) {
   int result = 0;
   if (Debug::test(DEBUG_MUTEX)) {
       cout << "locked" << endl;
   }

   if ((result = pthread_mutex_lock(&mutex)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::lock() - Could not lock mutex.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
    }
    tid = pthread_self();
};


void Mutex_Wrapper::unlock() throw(runtime_error)
{
   int result = 0;
   if (Debug::test(DEBUG_MUTEX)) {
       cout << "unlocked" << endl;
   }
   tid = (pthread_t)0;
   if ((result = pthread_mutex_unlock(&mutex)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::unlock() - Could not unlock mutex.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
   }
   tid = -1;
};


void Mutex_Wrapper::try_lock() throw(runtime_error)
{
   int result = 0;
   if ((result = pthread_mutex_trylock(&mutex)) != 0) {
      if (throw_exception) {
         throw runtime_error("POSIXMutex::tryLock() - Could not try-lock mutex.   Result: " + formatInt(result,4) + "  Description: " + std::string(strerror(result)));
      }
   }
};


pthread_t Mutex_Wrapper::getCurrent() const {
   return tid;
};


pthread_mutex_t& Mutex_Wrapper::getMutex(){
   return mutex;
};
